dict methods¶
dir({})
Output:
['__class__',
'__contains__',
'__delattr__',
'__delitem__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__setitem__',
'__sizeof__',
'__str__',
'__subclasshook__',
'clear',
'copy',
'fromkeys',
'get',
'items',
'keys',
'pop',
'popitem',
'setdefault',
'update',
'values']
Methods without double undescores:
[attr for attr in dir({}) if '__' not in attr]
Output:
['clear',
'copy',
'fromkeys',
'get',
'items',
'keys',
'pop',
'popitem',
'setdefault',
'update',
'values']
dict.clear()¶
D = {'one': 'uno'}
D['two'] = 'dos' # dict mutated: {'one': 'uno', 'two': 'dos'}
D.clear() # {} - remove all entries in a dict without destroying dict
D = {1: 1}
id(D) # 90038136
D.clear()
id(D) # 90038136
D = {'one': 'uno'}
D1 = D # create reference to a dict D
D, D1 # ({'one': 'uno'}, {'one': 'uno'})
D = {} # D pointed to empty dict (not reassigned to new dict)
D, D1 # ({}, {'one': 'uno'}) - D1 reference unchanged
D = D1 # ({'one': 'uno'}, {'one': 'uno'}) - recover entries in D
D.clear() # in case of clear()
D, D1 # ({}, {}) - both are cleared
dict.copy()¶
Shallow copy - only the keys will be copied.
The values will be the references to the values of the original dictionary.
Copy does not make a recursive copies of all dict substructures.
For deep copy we have to use “copy” python module
D = {'one': 'uno'}
D1 = D.copy()
D.clear() # changes in D will net be reflected to D1 if the changes are on level of the keys
D, D1 # ({}, {'one': 'uno'}) - D1 was not changed
# BUT in case of nested dictionary
D = {'one': {'spanish': 'uno',
'german': 'ein',
'french': 'un'}}
D1 = D.copy() # D1 is shallow copy with keys having refs to original values (sub-dict)
D['one'].clear() # clear just values corresponding the key 'one' i.e. sub-dictionary
D, D1 # ({'one': {}}, {'one': {}})
dict.get()¶
xs = {'one': 'uno'}
# xs['two'] # KeyError: 'two'
# Try to avoid exceptions:
def get_word(d, word, default=None):
if word in d:
return d[word]
return default
get_word(xs, 'one', 'unknown') # 'uno'
get_word(xs, 'two', 'unknown') # 'unknown'
# BUT this usage could not be considered ideomatic!
# Let's try to get length of the string which is belongs to dict:
english_word = 'two'
# spanish_word = xs[english_word] # Key Error ('two')
# spanish_word_length = len(spanish_word)
# spanish_word = xs.get(english_word)
# spanish_word_length = len(spanish_word) # Type Error ('NoneType') -> get() does not solve the problem
# Use get() ONLY if we can provide a SENSIBLE DEFAULT:
spanish_word = xs.get(english_word, '') #
spanish_word_length = len(spanish_word)
print(spanish_word_length) # 0
# BUT we can not blame .get() to avoid exceptions.
# This only delays this error and don't allow to father track it down.
# We SHOULD use the square bracket syntax and try...except block.
dict.update()¶
D = {1:1, 2:4, 3:9}
D1 = {1:0, 4:16} # another mapping
D1.update(D) # override values of the existing keys
D1
Output:
{1: 1, 4: 16, 2: 4, 3: 9}
dict.pop(), dict.popitem()¶
Retrieve and remove
xs = {'one': 'uno', 'two': 'dos'}
print(xs.pop('one')) # uno
xs # {'two': 'dos'}
xs.pop('one') # KeyError ('one')
xs.pop('one', 'default') # 'default'
xs.popitem() # retrieve next item (key:value pair) in dict and remove it - ('two', 'dos')
# items are not sorted => popitem() can return any item in dict
dict.keys(), dict.values(), dict.items()¶
d = {'uno': 'one', 'dos': 'two', 'tres': 'three'}
for key in d:
print(key, end=',') # uno,dos,tres,
for key in d.keys():
print(key, end=',') # uno,dos,tres,
for value in d.values():
print (value, end=',') # one,two,three,
for item in d.items():
print(item, end=',') # ('uno', 'one'),('dos', 'two'),('tres', 'three'),
# Note: The relative sorting of dict.keys(), dict.values(), dict.items() is garanteed.
# iterkeys, itervalues, iteritems in Python 2 - returns iterators of k,v,i of a dict
# viewkeys, viewvalues, viewitems in Python 2
d = {'uno': 'one', 'dos': 'two', 'tres': 'three'}
keys = d.keys() # symantec in Python 3 has changed. In Python 2 .keys() returns materialized list -
# duplicates of dict keys in memory - inefficient.
keys # dict_keys(['uno', 'dos', 'tres']) - special datatype, view on a keys of a dict
# In Python 3, if we mutate a dict, the keys will be mutated also
d['cinco'] = 'five'
d # {'uno': 'one', 'dos': 'two', 'tres': 'three', 'cinco': 'five'}
keys # dict_keys(['uno', 'dos', 'tres', 'cinco']) - include new key
# Do not manipulate dict keys while we iterating over it.
Example:
for key in d: # RuntimeError: dictionary changed size during iteration
if key == 'uno':
del d[key]
# Create a set() for such a keys
deleted_keys = set()
for key in d: # RuntimeError: dictionary changed size during iteration
if key == 'uno':
deleted_keys.add(key)
# and delete keys
for key in deleted_keys:
del d[key]
print(d) # {'dos': 'two', 'tres': 'three', 'cinco': 'five'}
dict.setdefault()¶
Manipulate the entries of a dict if not sure where the entries are exists or not.
student_courses = {'vinnie': {'calculus', 'diff eq'},
'arnold': {'calculus', 'linear algebra'},
'juan luis': {'real analysis'}}
student_courses['vinnie'].add('linear algebra')
print(student_courses)
# {'vinnie': {'calculus', 'diff eq', 'linear algebra'}, # OK
# 'arnold': {'calculus', 'linear algebra'},
# 'juan luis': {'real analysis'}}
student_courses['freddie'].add('linear algebra') # KeyError: 'freddie'
if 'freddie' not in student_courses:
student_courses['freddie'] = set()
student_courses['freddie'].add('linear algebra') # OK
# BUT more simple method to initialize the key is to use default value:
student_courses.setdefault('freddie', set()).add('linear algebra')
student_courses.setdefault('rosalie', set()).add('calculus')
student_courses.setdefault('rosalie', set()).add('linear algebra')
print(student_courses)
# {'vinnie': {'calculus', 'diff eq', 'linear algebra'},
# 'arnold': {'calculus', 'linear algebra'},
# 'juan luis': {'real analysis'},
# 'freddie': {'linear algebra'},
# 'rosalie': {'calculus', 'linear algebra'}}
dict.__missing__¶
class lowercase_dict(dict):
def __missing__(self, key):
return self[key.lower()]
d = lowercase_dict({'uno': 'one', 'dos': 'two'})
# after that:
d['uNo'] # 'one'
same as:
world = 'uNo'
d.get(world , d.get(world.lower())) # 'one'
dict-comprehensions¶
{x: x**2 for x in range(10) if x%2 == 0}
Example - Substitution cipher¶
from string import ascii_lowercase
# ascii_lowercase
from random import shuffle
# shuffle(ascii_lowercase) # TypeError: 'str' object does not support item assignment
alphabet = list(ascii_lowercase)
shuffle(alphabet)
codebook = {x: alphabet.pop() for x in ascii_lowercase}
print(codebook, end=';')
# {'a': 'g', 'b': 'v', 'c': 'q', 'd': 'p', 'e': 't', 'f': 'm', 'g': 'b', 'h': 'w', 'i': 'c', 'j': 'e', \
# 'k': 's', 'l': 'r', 'm': 'y', 'n': 'u', 'o': 'd', 'p': 'z', 'q': 'j', 'r': 'o', 's': 'a', 't': 'l', \
# 'u': 'f', 'v': 'h', 'w': 'x', 'x': 'k', 'y': 'i', 'z': 'n'};
message = 'python is great'
encoded = ''.join(codebook.get(char, '') for char in message)
# encoded # 'qcamwnyldgfua'
reverse_codebook = {v: k for k, v in codebook.items()} # values must be unique
print (''.join(reverse_codebook.get(m,'') for m in 'qcamwnyldgfua')) # pythonisgreat